package com.zdp.leetcodeMiddle;


import java.util.Deque;
import java.util.LinkedList;
import java.util.Stack;

/*
* 题目描述：
* 给定一个以字符串表示的非负整数 num，移除这个数中的 k 位数字，使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 1 :
输入: num = "1432219", k = 3
输出: "1219"
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
示例 2 :
输入: num = "10200", k = 1
输出: "200"
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。
示例 3 :
输入: num = "10", k = 2
输出: "0"
解释: 从原数字移除所有的数字，剩余为空就是0
来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/remove-k-digits
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
* */
public class 移掉k位数字_402 {
    public static void main(String[] args) {
        移掉k位数字_402 demo = new 移掉k位数字_402();
        String num = "12345264";
        int k = 4;
        String s = demo.removeKdigits(num, k);
        System.out.println(s);
    }

    /*
    * 解题思路： 要移去k位数 使剩下的数最小
    * 最小： 1、 剩下的数 位数越小越小
    *  2、 在前面位的数字越小越好
    *  都是移去k位，如何让位数越小 ？ ----> 生成还有前缀0的数
    *  第 i 个数一定要小于第 i-1个数
    * 用双端队列会比较好一点
    * */
    public String removeKdigits(String num, int k) {
        if(num.length() == k){
            // 特判
            return "0";
        }
        Stack<Character> stack = new Stack<>();
        int length = num.length();
        // 要添加进入栈的数一定要大于栈顶元素
        for(int i=0;i<length;i++){
            char temp = num.charAt(i);
            while(!stack.isEmpty() && stack.peek() > temp && k>0){
                // 保证加入栈的数大于栈顶元素
                // --->其实就是保证生成的数列 第i位一定是 小于 i-1位的
                stack.pop();
                k--;
            }
            stack.push(temp);
        }
        for(int i=0;i<k;i++){
            // 若 k >0 说明没有去除完毕，但生成的数列已经是按降序排列了
            // 所以从数列的后面去除相应个数的元素即可
            stack.pop();
        }
        // 生成字符串
        StringBuilder result = new StringBuilder();
        boolean preZero = true;
        while(!stack.isEmpty()){
            char temp = stack.pop();
            result.append(temp);
        }
        // 去除前缀0
        while(preZero && result.length() >1){
            if(result.charAt(result.length() -1 ) == '0'){
                result.deleteCharAt(result.length() -1);
            }else{
                preZero = false;
            }
        }
        return result.reverse().toString();
    }


    /*
    * 双端队列 省去 反转步骤  去除前缀0步骤也可以在转换成StringBuilder时操作
    * */
    public String removeKdigits1(String num, int k) {
        Deque<Character> deque = new LinkedList<Character>();
        int length = num.length();
        for (int i = 0; i < length; ++i) {
            char digit = num.charAt(i);
            while (!deque.isEmpty() && k > 0 && deque.peekLast() > digit) {
                deque.pollLast();
                k--;
            }
            deque.offerLast(digit);
        }

        for (int i = 0; i < k; ++i) {
            deque.pollLast();
        }

        StringBuilder ret = new StringBuilder();
        boolean leadingZero = true;
        while (!deque.isEmpty()) {
            char digit = deque.pollFirst();
            // 去除前缀0
            if (leadingZero && digit == '0') {
                continue;
            }
            leadingZero = false;
            ret.append(digit);
        }
        return ret.length() == 0 ? "0" : ret.toString();
    }

}
